#include "GError.h"
#include "GTaskResult.h"

namespace GEngine
{
	// Description: Constructor
	// Return:
	// Notes:
	// ----------------------------------------------------
	GTaskResult::GTaskResult()
	{
		Reset();
	}

	// Description: Destructor
	// Return:
	// Notes:
	// ----------------------------------------------------
	GTaskResult::~GTaskResult()
	{
	}

	// Description: Increases the referance count and manages the state
	// Return:
	// Notes: Should be called when a new task is scheduled()
	// ----------------------------------------------------
	void GTaskResult::IncreaseRef()
	{
		GInt32 Previous = RefCount.fetch_add(1, std::memory_order_release);
		if (Previous == 0)
		{
			// Task is just scheduled
			State.store(G_TS_SCHEDULED, std::memory_order_release);
		}
	}

	// Description: Decreases the referance count and manages the state
	// Return:
	// Notes: Should be called when a task is complete
	// ----------------------------------------------------
	void GTaskResult::DecreaseRef()
	{
		GInt32 Previous = RefCount.fetch_sub(1, std::memory_order_release);

		GUtil::GError::DebugCheck(Previous <= 0, "Minimum Ref count reached.");

		if (Previous == 1)
		{
			// Then task is complete
			State.store(G_TS_COMPLETED, std::memory_order_release);
		}
	}

	// Description: Resets the result to default state
	// Return:
	// Notes: When the result will be reused user should reset it
	// ----------------------------------------------------
	void GTaskResult::Reset()
	{
		RefCount.store(0, std::memory_order_release);
		State.store(G_TS_IDLE, std::memory_order_release);
	}

	// Description: Returns the state of the result
	// Return:
	// Notes:
	// ----------------------------------------------------
	GTaskState GTaskResult::GetState() const
	{
		return State.load(std::memory_order_acquire);
	}

	// Description: Returns if the given task is complete
	// Return:
	// Notes:
	// ----------------------------------------------------
	bool GTaskResult::CheckComplete(const GTaskResult& Result)
	{
		return Result.GetState() == G_TS_COMPLETED;
	}
}